const express = require('express');
const multer = require('multer');
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const path = require('path');
const open = require('open');

const CLIENT_ID = '你的client_id';
const CLIENT_SECRET = '你的client_secret';
const REDIRECT_URI = 'http://localhost:3001/oauth/callback'; // 你的回调地址

let ACCESS_TOKEN = '';
let REFRESH_TOKEN = '';

const app = express();
app.use(express.json());

// 上传目录
const UPLOAD_DIR = path.resolve(__dirname, 'uploads');
if (!fs.existsSync(UPLOAD_DIR)) fs.mkdirSync(UPLOAD_DIR);

// Multer配置
const storage = multer.diskStorage({
  destination: (req, file, cb) => cb(null, UPLOAD_DIR),
  filename: (req, file, cb) => cb(null, file.originalname)
});
const upload = multer({ storage });

// 1. 获取授权链接
app.get('/oauth/login', (req, res) => {
  const url = `https://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&scope=basic,netdisk&display=page`;
  res.redirect(url);
});

// 2. 授权回调，换取access_token
app.get('/oauth/callback', async (req, res) => {
  const code = req.query.code;
  const tokenUrl = `https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code=${code}&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}`;
  const result = await axios.get(tokenUrl);
  ACCESS_TOKEN = result.data.access_token;
  REFRESH_TOKEN = result.data.refresh_token;
  res.send('授权成功！你可以上传文件到百度网盘了。');
});

// 3. 上传文件到本地
app.post('/upload', upload.single('file'), async (req, res) => {
  if (!ACCESS_TOKEN) {
    return res.status(401).json({ success: false, message: '请先授权百度网盘！' });
  }
  const filePath = path.join(UPLOAD_DIR, req.file.filename);
  try {
    // 上传到百度网盘
    const result = await uploadToBaiduNetdisk(filePath, req.file.originalname, ACCESS_TOKEN);
    res.json({ success: true, baidu: result });
  } catch (e) {
    res.status(500).json({ success: false, error: e.message });
  }
});

// 4. 上传到百度网盘的完整流程
async function uploadToBaiduNetdisk(filePath, fileName, access_token) {
  const stat = fs.statSync(filePath);
  const size = stat.size;
  const block_list = [await md5File(filePath)]; // 简化：小文件直接全量MD5
  // 1. 预上传
  const preRes = await axios.post(
    `https://pan.baidu.com/rest/2.0/xpan/file?method=precreate&access_token=${access_token}`,
    new URLSearchParams({
      path: `/apps/你的应用名/${fileName}`,
      size: size + '',
      isdir: '0',
      autoinit: '1',
      rtype: '1',
      block_list: JSON.stringify(block_list)
    }),
    { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
  );
  const uploadid = preRes.data.uploadid;
  // 2. 上传分片（这里只演示单分片）
  const form = new FormData();
  form.append('file', fs.createReadStream(filePath));
  await axios.post(
    `https://d.pcs.baidu.com/rest/2.0/pcs/superfile2?method=upload&access_token=${access_token}&type=tmpfile&path=/apps/你的应用名/${fileName}&uploadid=${uploadid}&partseq=0`,
    form,
    { headers: form.getHeaders() }
  );
  // 3. 合并分片
  const createRes = await axios.post(
    `https://pan.baidu.com/rest/2.0/xpan/file?method=create&access_token=${access_token}`,
    new URLSearchParams({
      path: `/apps/你的应用名/${fileName}`,
      size: size + '',
      isdir: '0',
      uploadid,
      block_list: JSON.stringify(block_list),
      rtype: '1'
    }),
    { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
  );
  return createRes.data;
}

// 计算文件MD5
function md5File(filePath) {
  return new Promise((resolve, reject) => {
    const crypto = require('crypto');
    const hash = crypto.createHash('md5');
    const stream = fs.createReadStream(filePath);
    stream.on('data', chunk => hash.update(chunk));
    stream.on('end', () => resolve(hash.digest('hex')));
    stream.on('error', reject);
  });
}

// 启动服务
const PORT = 3001;
app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`);
  // 自动打开授权页面
  open(`http://localhost:${PORT}/oauth/login`);
});